package com.example.musicbox.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.musicbox.config.MyException;
import com.example.musicbox.entity.MCatalogue;
import com.example.musicbox.entity.MLog;
import com.example.musicbox.entity.MUser;
import com.example.musicbox.entity.dto.LoginDto;
import com.example.musicbox.entity.dto.RegisterDto;
import com.example.musicbox.entity.dto.UserDto;
import com.example.musicbox.enums.AboutMusic;
import com.example.musicbox.enums.LogDoType;
import com.example.musicbox.mapper.MCatalogueMapper;
import com.example.musicbox.mapper.MLogMapper;
import com.example.musicbox.mapper.MUserMapper;
import com.example.musicbox.service.MUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.musicbox.utils.EmailSender;
import com.example.musicbox.utils.GeneratorToken;
import com.example.musicbox.utils.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 帅哥是我
 * @since 2022-08-01
 */
@Service
public class MUserServiceImpl extends ServiceImpl<MUserMapper, MUser> implements MUserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MUserServiceImpl.class);

    @Resource
    private MUserMapper mUserMapper;

    @Resource
    private EmailSender emailSender;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private GeneratorToken generatorToken;

    @Value("${redisConf.expire}")
    private Integer expireTime;

    @Resource
    private MCatalogueMapper mCatalogueMapper;

    @Resource
    private MLogMapper mLogMapper;

    @Resource
    private MLogServiceImpl mLogService;

    /**
     * 用户注册
     *
     * @param registerDto
     * @return
     */
    @Transactional
    @Override
    public Result userRegister(RegisterDto registerDto) {
        try {
            Integer phoneCount = mUserMapper.countPhone(registerDto.getUphone());
            Integer emailCount = mUserMapper.countEmail(registerDto.getUemail());
            if (phoneCount > 0) {
                throw new MyException("该电话已被注册");
            }
            if (emailCount > 0) {
                throw new MyException("该邮箱已被注册");
            }
            String emailKey = "xyc_" + registerDto.getUemail();
            String key = (String) redisTemplate.opsForValue().get(emailKey);
            MUser user = new MUser();
            if (key.equals(registerDto.getCode())) {

                String upassword = registerDto.getUpassword();
                upassword = DigestUtils.md5DigestAsHex(upassword.getBytes());
                registerDto.setUpassword(upassword);
                BeanUtils.copyProperties(registerDto, user);
                mUserMapper.insert(user);
                //完成用户音乐目录初始化
                MCatalogue catalogue1 = MCatalogue.builder()
                        .cName("本地目录")
                        .cSort(1)
                        .uid(user.getId())
                        .build();
                MCatalogue catalogue2 = MCatalogue.builder()
                        .cName("我的收藏")
                        .cSort(2)
                        .uid(user.getId())
                        .build();
                mCatalogueMapper.insert(catalogue1);
                mCatalogueMapper.insert(catalogue2);
                //完成用户注册日志增加
                MLog mLog = MLog.builder()
                        .uid(user.getId())
                        .uname(user.getUsername())
                        .dowhat("用户注册")
                        .lType("1")
                        .doType("6")
                        .build();
                mLogMapper.insert(mLog);
                redisTemplate.delete(emailKey);
                return Result.ok("用户注册成功");
            } else {
                throw new MyException("验证码输入有误");
            }
        } catch (Exception e) {
            LOGGER.error("用户注册信息初始化失败");
            throw new MyException(e.getMessage());
        }

    }


    /**
     * 用户登录
     *
     * @param loginDto
     * @return
     */
    @Transactional
    @Override
    public Result userLogin(LoginDto loginDto) {
        try {
            UserDto userDto = new UserDto();
            //登录标识，“pass”表示为账号密码登录
            if (loginDto.getLogintype().equals("pass")) {
                String upassword = loginDto.getUpassword();
                upassword = DigestUtils.md5DigestAsHex(upassword.getBytes());
                try {
                    MUser mUser = mUserMapper.userLogin(loginDto.getUphone(), upassword);
                    //用户状态，当状态为1时，需要请求管理员解冻用户权限
                    if (mUser.getUstatus().equals("1")) {
                        throw new MyException("请联系管理");
                    }
                    mUser.setUpassword(null);
                    mUser.setLastloigndata(LocalDateTime.now());
                    BeanUtils.copyProperties(mUser, userDto);
                    String token = generatorToken.getToken(userDto);
                    redisTemplate.opsForValue().set(token, mUser.getId(), expireTime, TimeUnit.HOURS);
                    //日志信息记录
                    mLogService.insertLog("用户账号密码登录", AboutMusic.NOTHINGABOUTMUSIC, null, LogDoType.INSERT, token);
                    return Result.ok("用户登录成功").put("user", mUser).put("token", token);
                } catch (Exception e) {
                    throw new MyException("信息填写错误，请重新登录");
                }
                //登录标识，“email”表示为邮箱验证码登录
            } else if (loginDto.getLogintype().equals("email")) {
                String key = "xyc_" + loginDto.getUemail();
                String emailCode = (String) redisTemplate.opsForValue().get(key);
                if (loginDto.getCode().equals(emailCode)) {
                    redisTemplate.delete(key);
                    QueryWrapper<MUser> wrapper = new QueryWrapper<>();
                    wrapper.eq("uEmail", loginDto.getUemail());
                    MUser mUser = mUserMapper.selectOne(wrapper);
                    //用户状态，当状态为1时，需要请求管理员解冻用户权限
                    if (mUser.getUstatus().equals("1")) {
                        throw new MyException("请联系管理");
                    }
                    //将密码清空
                    mUser.setUpassword(null);
                    BeanUtils.copyProperties(mUser, userDto);
                    String token = generatorToken.getToken(userDto);
                    //登录成功之后见token存储进redis中
                    redisTemplate.opsForValue().set(token, mUser.getId(), expireTime, TimeUnit.HOURS);
                    //日志信息记录
                    mLogService.insertLog("邮箱验证码登录", AboutMusic.NOTHINGABOUTMUSIC, null, LogDoType.INSERT, token);
                    return Result.ok("用户登录成功").put("user", mUser).put("token", token);
                } else {
                    throw new MyException("验证码输入有误");
                }
                //登录标识错误
            } else {
                throw new MyException("登录异常，请重新登录");
            }
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
    }
}
